package com.kins.easycare.core.utils;

import io.micrometer.common.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @Description:
 * @Author: 申科
 * @Date:2025/11/12 11:42
 */
@Component
public class SpringContextHolder implements ApplicationContextAware {

    private static DefaultListableBeanFactory defaultListableBeanFactory;

    private static ApplicationContext applicationContext = null;

    private static Logger log = LoggerFactory.getLogger(SpringContextHolder.class);
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        log.debug("Injecting apx into SpringContextUtil:" + applicationContext);
        if(SpringContextHolder.applicationContext !=null){
            log.warn("Original apx will be override:" + applicationContext);
        }
        SpringContextHolder.applicationContext = applicationContext;
    }
    /**
     * 获取ApplicationConte
     */
    public static ApplicationContext getApplicationContext() {
        assertContextInjected();//判断application是否注入
        return applicationContext;
    }
    /**
     * 获取bean
     */
    public static <T> T getBean(Class<T> requiredType) {
        assertContextInjected();
        return applicationContext.getBean(requiredType);
    }

    public static <T> T getBean(String name) {
        assertContextInjected();
        return (T) applicationContext.getBean(name);
    }

    /**
     *
     */
    private static void assertContextInjected() {
        if (applicationContext == null) {
            throw new IllegalStateException("Application have not been injected.");
        }
    }

    public static void registerBean(String beanName,Class<?> clazz){
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
        defaultListableBeanFactory.registerBeanDefinition(beanName, beanDefinitionBuilder.getRawBeanDefinition());
    }

    public static void unregisterBean(String name){defaultListableBeanFactory.removeBeanDefinition(name);}

    public static void registerBeanFromJar(String jarFile, String interfaceName)throws Exception{
        try{
            File f = new File(jarFile);
            URL url1 = f.toURI().toURL();
            URLClassLoader myClassLoader = new URLClassLoader(new URL[]{url1}, Thread.currentThread().getContextClassLoader());

            //通过jarFile和jarEntty得到所有的类
            jarFile jar = new JarFile(jarFile);

            //返回zip文件条目的枚举
            Enumeration enumFiles = jar.entries();
            JarEntry entry;
            //测试此枚举是否包含更多的元素
            while(enumFiles.hasMoreElements()){
                entry = (JarEntry) enumFiles.nextElement();
                if(entry.getName().indexOf("META-INF")<0){
                    String classFullName = entry.getName();
                    if(!classFullName.endsWith(".class")){
                        classFullName = classFullName.substring(0, classFullName.length()-1);
                    }else{
                        //去掉.class
                        String className = classFullName.substring(0,classFullName.length()-6).replace("/",".");
                        Class<?> infs = myclass.getInterfaces();
                        boolean infExistFlag = false;
                        for (Class<?> inf : infs){
                            if(StringUtils.equals(inf.getName(),interfaceName)){
                                infExistFlag =true;
                            }
                        }
                        if(infExistFlag){
                            String clazzFullName = myclass.getName();
                            String clazzName = CharSequenceUtil.lowerFirst(clazzFullName.substring(clazzFullName.lastIndexOf(".")+1));
                            boolean beanExistFlag = true;
                            try{
                                getBean(clazzName);

                            }catch(Exception e){
                                beanExistFlag = false;
                            }
                            if(beanExistFlag){
                                unregisterBean(clazzName);
                                registerBean(clazzName,myclass);

                            }else{
                                registerBean(className,myclass);
                            }
                        }
                    }
                }
            }


    }catch(Exception e){
        e.printStackTrace();
    }
}}
